﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;

namespace Dycox.Drawing
{
    public abstract class DiagramShape : IDisposable
    {
        public void Draw(DrawShapeArgs renderer)
        {
            if (_outlinePath != null)
            {
                this.DrawShape(renderer);

                if (renderer.DrawHotPoints)
                    DrawHotPoints(renderer.Graphics);
            }
        }

        private void DrawHotPoints(Graphics g)
        {
            if (_hotPoints != null && _hotPoints.Count > 0)
            {
                float size = 3;
                Pen pen = new Pen(Color.Blue, 1);

                foreach (HotPoint hp in _hotPoints)
                {
                    float x = hp.X, y = hp.Y;

                    g.DrawLine(pen, x - size, y - size, x + size, y + size);
                    g.DrawLine(pen, x + size, y - size, x - size, y + size);
                }

                pen.Dispose();
            }
        }

        protected abstract void DrawShape(DrawShapeArgs g);

        public abstract bool HitTest(Point location, Graphics g);

        private GraphicsPath _outlinePath;

        protected GraphicsPath OutlinePath
        {
            get { return _outlinePath; }
            set
            {
                if (_outlinePath != value)
                {
                    if (_outlinePath != null)
                        _outlinePath.Dispose();
                    _outlinePath = value;
                }
            }
        }

        private List<HotPoint> _hotPoints;

        public HotPoint[] HotPoints
        {
            get
            {
                if (_hotPoints != null) return _hotPoints.ToArray();
                else return new HotPoint[0];
            }
        }

        public event EventHandler HotPointsChanged;

        protected void SetHotPoints(params PointF[] points)
        {
            if (_hotPoints == null) _hotPoints = new List<HotPoint>();
            else _hotPoints.Clear();

            foreach (PointF hp in points)
            {
                _hotPoints.Add(new HotPoint(hp, _hotPoints.Count + 1));
            }

            OnHotPointsChanged(EventArgs.Empty);
        }

        protected virtual void OnHotPointsChanged(EventArgs e)
        {
            if (HotPointsChanged != null)
                HotPointsChanged(this, e);
        }

        public HotPoint GetHotPoint(int id)
        {
            if (_hotPoints != null)
            {
                int index = id - 1;
                if (index >= 0 && index < _hotPoints.Count)
                    return _hotPoints[index];
            }

            return HotPoint.Empty;
        }

        private Color _textColor = Color.Black;

        public Color TextColor
        {
            get { return _textColor; }
            set { _textColor = value; }
        }

        private Color _fillColor = Color.White;

        public Color FillColor
        {
            get { return _fillColor; }
            set { _fillColor = value; }
        }

        private Color _lineColor = Color.Black;

        public Color LineColor
        {
            get { return _lineColor; }
            set { _lineColor = value; }
        }

        private float _lineWidth = 1f;

        public float LineWidth
        {
            get { return _lineWidth; }
            set { _lineWidth = value; }
        }

        private DashStyle _lineDashStyle;

        public DashStyle LineDashStyle
        {
            get { return _lineDashStyle; }
            set { _lineDashStyle = value; }
        }

        private Font _font;

        public Font Font
        {
            get { return _font; }
            set { _font = value; }
        }

        protected virtual Pen CreateLinePen(bool ignoreColor)
        {
            if (_lineWidth > 0 && (ignoreColor || !_lineColor.IsEmpty))
            {
                Pen pen = new Pen(_lineColor, _lineWidth);
                pen.DashStyle = _lineDashStyle;
                
                return pen;
            }
            else
                return null;
        }

        protected virtual Brush CreateFillBrush()
        {
            if (!_fillColor.IsEmpty)
            {
                Brush br;

                br = new SolidBrush(_fillColor);

                return br;
            }
            else
                return null;
        }

        protected virtual Brush CreateTextBrush()
        {
            if (!_textColor.IsEmpty)
            {
                Brush br;

                br = new SolidBrush(_textColor);

                return br;
            }
            else
                return null;
        }

        private string _text;

        public string Text
        {
            get { return _text; }
            set { _text = value; }
        }

        public virtual void Dispose()
        {
            if (_outlinePath != null)
                _outlinePath.Dispose();
            if (_font != null && !_font.IsSystemFont)
                _font.Dispose();
        }
    }

}
